package com.giraffe.device.service.impl;


import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.giraffe.common.core.enums.DelFlagStatusEnum;
import com.giraffe.common.core.enums.EnableStatusEnum;
import com.giraffe.common.redis.service.RedisService;
import com.giraffe.device.domain.Device;
import com.giraffe.device.pojo.dto.DeviceDTO;
import com.giraffe.device.repository.DeviceRepository;
import com.giraffe.device.service.DeviceService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.sql.Wrapper;
import java.util.List;

/**
 * 产品(Product)表服务实现类
 *
 * @author makejava
 * @since 2023-02-14 10:39:59
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    @Resource
    private DeviceRepository deviceRepository;
    @Resource
    private RedisService redisService;
    private static final String DEVICE_CACHE_KEY = "giraffe:device:";

    /**
     * 通过主键查询单条数据
     *
     * @param id 主键
     * @return 单条数据
     */
    @Override
    public Device findById(String id) {
        if (StringUtils.isBlank(id)) {
            return null;
        }
        return this.deviceRepository.getById(id);
    }

    /**
     * 新增数据
     *
     * @param product 实体对象
     * @return 新增结果
     */
    @Transactional
    @Override
    public Device create(Device product) {
        this.deviceRepository.saveOrUpdate(product);
        return product;
    }

    /**
     * 修改新据
     *
     * @param product 实体对象
     * @return 修改结果
     */
    @Transactional
    @Override
    public Device update(Device product) {
        this.deviceRepository.saveOrUpdate(product);
        return product;
    }

    /**
     * 删除数据
     *
     * @param idList 主键结合
     * @return 删除结果
     */
    @Transactional
    @Override
    public void delete(List<String> idList) {
        Validate.isTrue(!CollectionUtils.isEmpty(idList), "删除数据时，主键集合不能为空！");
        List<Device> products = this.deviceRepository.findByIds(idList);
        Validate.isTrue(!CollectionUtils.isEmpty(products), "删除数据时，未查询到需要删除的数据！");
        products.stream().forEach(product -> product.setDelFlag(DelFlagStatusEnum.DELETE.getCode()));
        this.deviceRepository.saveOrUpdateBatch(products);
    }

    /**
     * 启用（单个或者批量）
     *
     * @param idList 主键结合
     * @return 启用结果
     */
    @Transactional
    @Override
    public void enable(List<String> idList) {
        Validate.isTrue(!CollectionUtils.isEmpty(idList), "启用数据时，主键集合不能为空！");
        List<Device> products = this.deviceRepository.findEnableStatusByIds(EnableStatusEnum.DISABLE, idList);
        Validate.isTrue(!CollectionUtils.isEmpty(products), "启用数据时，未查询到需要启用的数据！");
        products.stream().forEach(product -> product.setEnableStatus(EnableStatusEnum.ENABLE.getCode()));
        this.deviceRepository.saveOrUpdateBatch(products);
    }

    /**
     * 禁用（单个或者批量）
     *
     * @param idList 主键结合
     * @return 禁用结果
     */
    @Transactional
    @Override
    public void disable(List<String> idList) {
        Validate.isTrue(!CollectionUtils.isEmpty(idList), "禁用数据时，主键集合不能为空！");
        List<Device> products = this.deviceRepository.findEnableStatusByIds(EnableStatusEnum.ENABLE, idList);
        Validate.isTrue(!CollectionUtils.isEmpty(products), "禁用数据时，未查询到需要禁用的数据！");
        products.stream().forEach(product -> product.setEnableStatus(EnableStatusEnum.DISABLE.getCode()));
        this.deviceRepository.saveOrUpdateBatch(products);
    }

    /**
     * 根据设备ID获取设备信息
     * @param deviceId 设备ID
     * @return 设备信息DTO
     */
    @Override
    public DeviceDTO getDevice(String deviceId) {
        // 创建设备信息DTO对象
        DeviceDTO dto;
        // 尝试从Redis缓存中获取设备信息
        dto = redisService.getCacheObject(deviceId);
        if (!ObjectUtils.isEmpty(dto)) {
            // 如果从缓存中获取到设备信息，则直接返回
            return dto;
        }
        dto = new DeviceDTO();
        // 如果缓存中没有设备信息，则从数据库中查询设备
        Device device = deviceRepository.lambdaQuery().eq(Device::getDeviceId, deviceId).one();
        // 如果设备为空，则返回null
        if (ObjectUtils.isEmpty(device)) {
            return null;
        }
        // 将设备属性复制到设备信息DTO对象中
        BeanUtils.copyProperties(device, dto);
        // 将设备信息保存到Redis缓存中
        redisService.setCacheObject(DEVICE_CACHE_KEY+deviceId, dto);
        return dto;
    }


    /**
     * 设置设备状态
     * @param dto 设备信息DTO对象
     * @return 返回布尔值，表示是否成功更新设备状态
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean setDeviceStatus(DeviceDTO dto) {
        return deviceRepository.update(new UpdateWrapper<Device>().set("device_status", dto.getDeviceStatus()).eq("device_id", dto.getDeviceId()));
    }

}

